<template>
  <h2>ts-demo</h2>
  <button @click="fn(-1)">-</button>
  <span>{{ count }}</span>
  <button @click="fn(1)">+</button>

  <p>doubleCount: {{ doubleCount }}</p>

  <hr />

  <input type="text" v-model="value" />
  <button @click="add">添加</button>
  <ul>
    <li v-for="item in list" :key="item.id">
      {{ item.name }} - <button @click="remove(item.id)">删除</button>
    </li>
  </ul>

  <hr />

  <child :count="count"></child>

  <hr />

  <p>{{ state.a }}</p>
  <p>{{ state.b }}</p>
</template>

<script lang="ts">
import {
  defineComponent,
  ref,
  computed,
  watch,
  onMounted,
  reactive,
  provide,
} from "vue";
import Child from "./Child.vue";

interface ObjType {
  name: string;
  id: number;
}

interface StateType {
  a: number;
  b: boolean;
}

export default defineComponent({
  components: {
    Child,
  },
  setup() {
    // 在定义ref变量的时候，要使用泛型的写法
    const count = ref<number>(3);

    // 函数的参数和返回值都需要加上类型
    const fn = (n: number): void => {
      // count.value = "hello";
      count.value += n;
    };

    // 计算属性和ref变量一样要加泛型
    const doubleCount = computed<number>(() => count.value * 2);

    // 侦听器不需要加类型
    watch(count, (val): void => {
      console.log("count改变了", val);
    });

    // 生命周期基本也不需要加类型
    onMounted((): void => {
      console.log(123);
    });

    const value = ref<string>("");
    const list = ref<ObjType[]>([
      { name: "zhangsan", id: 1 },
      { name: "lisi", id: 2 },
    ]);
    const add = (): void => {
      list.value.push({ name: value.value, id: new Date().getTime() });
    };
    const remove = (id: number): void => {
      list.value = list.value.filter((item) => item.id !== id);
    };

    const state: StateType = reactive({
      a: 3,
      b: true,
    });

    // 事件处理函数的event参数的类型是Event
    // function handleChange(event: Event) {
    //   console.log((event.target as HTMLInputElement).value);
    // }

    // 依赖注入
    provide("name", "zhangsan");

    return { count, fn, doubleCount, value, list, add, remove, state };
  },
});
</script>
